package com.example.springboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springboot.common.exception.ServiceException;
import com.example.springboot.common.utils.utils.MenuHelper;
import com.example.springboot.entity.Permission;
import com.example.springboot.entity.RolePermission;
import com.example.springboot.entity.dto.AssginMenuDto;
import com.example.springboot.entity.vo.MetaVo;
import com.example.springboot.entity.vo.RouterVo;
import com.example.springboot.mapper.PermissionMapper;
import com.example.springboot.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RolePermissionServiceImpl rolePermissionService;

    @Override
    public List<Permission> findNodes() {
        List<Permission> sysMenus = permissionMapper.selectList(null);
        return MenuHelper.buildTree(sysMenus);
    }

    @Override
    public List<Permission> findMenuByRoleId(Long roleId) {
        LambdaQueryWrapper<Permission> wrapperSysMenu = new LambdaQueryWrapper<>();
        List<Permission> allSysMenuList = baseMapper.selectList(wrapperSysMenu);

        LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RolePermission::getRoleid, roleId);
        List<RolePermission> sysRoleMenus = rolePermissionService.list(wrapper);

        List<Integer> menuIds = sysRoleMenus.stream().map(RolePermission::getPid).collect(Collectors.toList());

        allSysMenuList.forEach(item -> {
            item.setSelect(menuIds.contains(item.getPid()));
        });
        return MenuHelper.buildTree(allSysMenuList);
    }

    //根据roleId 查询菜单名称
    @Override
    public List<String> findMenuNameByRoleId(Long roleId) {
        return permissionMapper.findMenuNameByRoleId(roleId);
    }

    @Override
    public void doAssign(AssginMenuDto assginMenuDto) {
        LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RolePermission::getRoleid, assginMenuDto.getRoleId());
        rolePermissionService.remove(wrapper);

        List<Integer> menuIdList = assginMenuDto.getMenuIdList();
        menuIdList.forEach(item -> {
            if (!StringUtils.isEmpty(item)) {
                RolePermission sysRoleMenu = new RolePermission();
                sysRoleMenu.setPid(item);
                sysRoleMenu.setRoleid(assginMenuDto.getRoleId());
                rolePermissionService.save(sysRoleMenu);
            }
        });
    }

    @Override
    public void removeMenuById(Long id) {
        LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Permission::getParentid, id);
        Integer count = baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new ServiceException("菜单不能删除", "201");
        }
        baseMapper.deleteById(id);
    }

    @Override
    public List<RouterVo> findUserMenuListByUserId(Long userId) {
        List<Permission> sysMenuList = new ArrayList<>();
        //超级管理员显示所有菜单
        if (userId == 1) {
            LambdaQueryWrapper<Permission> wrapper = new LambdaQueryWrapper<>();
            wrapper.orderByAsc(Permission::getOrdernum);
            sysMenuList = baseMapper.selectList(wrapper);
        } else {
            sysMenuList = baseMapper.findMenuListByUserId(userId);
        }
        List<Permission> sysMenuTreeList = MenuHelper.buildTree(sysMenuList);
        List<RouterVo> routerList = this.buildRouter(sysMenuTreeList);
        return routerList;
    }

    private List<RouterVo> buildRouter(List<Permission> menus) {
        List<RouterVo> routers = new ArrayList<>();
        menus.forEach(menu -> {
            RouterVo router = new RouterVo();
            router.setHidden(false);
            router.setAlwaysShow(false);
            router.setPath(getRouterPath(menu));
            router.setName(getRouteName(menu));
            router.setComponent(menu.getComponent());
            router.setMeta(new MetaVo(menu.getPermissiondes(), menu.getIcon()));
            List<Permission> children = menu.getChildren();
            if ("C".equals(menu.getType())) {
                List<Permission> hiddenMenuLists = children.stream().filter(item ->
                        !StringUtils.isEmpty(item.getComponent())
                ).collect(Collectors.toList());

                hiddenMenuLists.forEach(hiddenMenuList -> {
                    RouterVo hiddenRouter = new RouterVo();
                    hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setName(getRouteName(hiddenMenuList));
                    hiddenRouter.setPath(getRouterPath(hiddenMenuList));
                    hiddenRouter.setComponent(hiddenMenuList.getComponent());
                    hiddenRouter.setMeta(new MetaVo(hiddenMenuList.getPermissiondes(), hiddenMenuList.getIcon()));
                    routers.add(hiddenRouter);
                });
            } else {
                if (!CollectionUtils.isEmpty(children)) {
                    if (children.size() > 0) {
                        router.setAlwaysShow(true);
                        router.setComponent("layout/index");
                    }
                    router.setChildren(buildRouter(children));
                }
            }
            routers.add(router);
        });
        return routers;
    }

    private String getRouterPath(Permission menu) {
        String routerPath = "/" + menu.getPath();
        if (menu.getParentid() != 0) {
            routerPath = menu.getPath();
        }
        return routerPath;
    }

    /**
     * 获取路由名称
     *
     * @param menu 菜单信息
     * @return 路由名称
     */
    public String getRouteName(Permission menu) {
        return StringUtils.capitalize(menu.getPath());
    }
}
